//--------------------------------------------
//
// copyright@2008,all right reserved by ax.
//
//
//     PROJECT   :   futrue
//
//     FILE      :   BaseMsg.h
//
//     PURPOSE   :   futrue project main file
//   
//     DATE      :   2008/10/01
//
//     AUTHOR    :   ax
//
//--------------------------------------------
#ifndef __FUTRUE_BASE_MSG_POOL_H__
#define __FUTRUE_BASE_MSG_POOL_H__
#include "BaseMsg.h"
#include "LockImp.h"

#include <list>
#include <map>

template <typename T>
class ObjPool
{
public:
	ObjPool(int nMaxObj = 10):m_nMaxObj(nMaxObj)
	{
		 m_nCurObj = 0;
		 m_pObjPool = 0;
		 Init();
	}
	~ObjPool()
	{
		UnInit();
	}

public:
	T*  Alloc()
	{
		if(m_nCurObj <= 0 || m_pObjPool == 0)
			return NULL;

		T* t = m_pObjPool[ m_nCurObj -1 ];
		m_nCurObj -= 1;
		m_pObjPool[m_nCurObj] = 0;

		return t;
	}

	void Free(T* t)
	{
		if(m_nCurObj >= m_nMaxObj)
		{
			delete t;
			assert(0);
			return;
		}
		m_pObjPool [ m_nCurObj ++ ] = t;
	}

public:

private:
	void Init()
	{
		if(m_pObjPool)
			return;

	    m_pObjPool = new T* [m_nMaxObj];
		m_nCurObj = 0;
	}
	void UnInit()
	{
		int i = 0;
		for(; i < m_nCurObj && m_pObjPool; i++)
		{
			T* t = m_pObjPool[i];
			if(t)
			delete t;
		}
		if(m_pObjPool)
			delete[] m_pObjPool;
		m_pObjPool = 0;
		m_nCurObj = 0;
	}
protected:
	T**    m_pObjPool;
	const  int    m_nMaxObj;
	int    m_nCurObj;
};

 
class BaseMsgPool
{
public:
	BaseMsgPool()
	{
		m_cMapPool.clear();
	}
	~BaseMsgPool()
	{
		ObjPool<BaseMsg>* p = 0;
		std::map<int,ObjPool<BaseMsg>* >::iterator it = m_cMapPool.begin();
		for(; it != m_cMapPool.end(); )
		{
			p = it->second;
			m_cMapPool.erase(it);

			delete p;

			it = m_cMapPool.begin();
		}
	}

public:
	BaseMsg*  Alloc(int nSize)
	{
		std::map<int,ObjPool<BaseMsg>* >::iterator it = m_cMapPool.find(nSize);
		if(it == m_cMapPool.end())
		{
			BaseMsg* pNew = new BaseMsg(nSize);
			return pNew;
		}

		BaseMsg* p = it->second.Alloc();

		if(p == NULL)
		{
			BaseMsg* pNew = new BaseMsg(nSize);
			return pNew;
		}

		return p;
	}

	void Free(BaseMsg* pMsg)
	{
		std::map<int,ObjPool<BaseMsg>>::iterator it = m_cMapPool.find(pMsg->GetMaxSize());
		if(it == m_cMapPool.end())
		{
			ObjPool<BaseMsg> *pPool = new ObjPool<BaseMsg>;
			pPool->Free(pMsg);

			std::map<int,ObjPool<BaseMsg>* >::value_type val(pMsg->GetMaxSize(),pPool);
			m_cMapPool.insert(val);
			return;
 		}
		it->second->Free(pMsg);
	}
	 
private:	
	std::map<int,ObjPool<BaseMsg>* >   m_cMapPool;
 };

template <typename T>
class MultiObjPool
{
public:
	MultiObjPool(int nMax):m_cPool(nMax)
	{

	}
	~MultiObjPool()
	{
	}

	T* Alloc()
	{
		AutoLockImp  al(m_cLock);
		return m_cPool.Alloc();
	}

	void Free(T* t)
	{
		AutoLockImp  al(m_cLock);
		return m_cPool.Free(t);
	}

protected:
	LockImp     m_cLock;
	ObjPool<T>  m_cPool;
};

#endif